// 无缓冲 channel 还被用来实现 1 对 n 的信号通知机制。这样的信号通知机制，常被用于协调多个 Goroutine 一起工作

package main

import (
	"fmt"
	"sync"
	"time"
)

// 通知信号
type signal struct{}

func worker(i int) {
	fmt.Printf("worker%d: 正工作中\n", i)
	time.Sleep(time.Second)
}
func spawnGroup(f func(i int), num int, groupSignal <-chan signal) <-chan signal {
	c := make(chan signal)
	var wg sync.WaitGroup

	for i := 0; i < num; i++ {
		wg.Add(1)
		go func(i int) {
			<-groupSignal
			fmt.Printf("worker %d: 开始工作\n", i)
			f(i)
			wg.Done()
		}(i + 1)
	}

	go func() {
		wg.Wait()
		c <- signal{}
	}()
	return c
}
func main() {
	println("开始一个worker group")
	groupSignal := make(chan signal)
	// 创建5个worker goroutine，并阻塞在无缓冲groupSignal上
	c := spawnGroup(worker, 5, groupSignal)
	time.Sleep(5 * time.Second)
	fmt.Println("工作组中的工人开始工作")
	// 停止阻塞，同时开始工作
	close(groupSignal)
	<-c
	fmt.Println("worker group工作结束")
}

/*
开始一个worker group
工作组中的工人开始工作
worker 2: 开始工作
worker2: 正工作中
worker 5: 开始工作
worker5: 正工作中
worker 4: 开始工作
worker4: 正工作中
worker 3: 开始工作
worker3: 正工作中
worker 1: 开始工作
worker1: 正工作中
worker group工作结束
*/
